home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 02 - 1986 / 02.09 Sep 86.sit / 02.09 Sep 86 / sources boyd / OverView.p / OverView.p
Encoding:
Text File  |  1986-07-14  |  11.1 KB  |  363 lines  |  [TEXT/MPS ]

  1. UNIT OverView; 
  2. {Version 1.0 Saturday, July 12, 1986 9:47:53 PM
  3.  by Scott T. Boyd, the MacHax™ Group
  4.  Many thanks to Greg Marriott of SoftWare To Go,
  5.  also a member of the MacHax™ Group}
  6.  
  7. {--------------------------------------------------------------------------}
  8. INTERFACE
  9.  
  10. {Compiler Switch Settings}
  11. {$R+}
  12. {$OV+}
  13.  
  14. uses MemTypes, QuickDraw, OSIntf, ToolIntf, SANE;
  15.  
  16. const
  17.     MenuBarHeight    =  20;    {Height of menu bar in pixels}
  18.     TitleBarHeight    =  18;    {Height of window title bar in pixels}
  19.     ScreenMargin    =   4;    {Width of "safety margin" around edge of screen}
  20.     SBarHeight        =  15;    {Height of scroll bar}
  21.     SBarWidth        =  15;    {Width of scroll bar}
  22.  
  23. Procedure NewOverView( var OV_pagePict : bitMap; 
  24.                        var OV : WindowPtr; 
  25.                        viewRect : Rect;
  26.                        factor : Real );
  27. Procedure UpdateOverView( Procedure drawProc;
  28.                           OV_pagePict : bitMap);
  29. Procedure OverViewSelect( where: Point; 
  30.                           viewRect : Rect; VAR scrollPosition : Point; 
  31.                           VAR OV : WindowPtr; VAR OV_pagePict : bitMap; 
  32.                           HScrollBar,VScrollBar : ControlHandle);
  33.  
  34. {--------------------------------------------------------------------------}
  35. IMPLEMENTATION
  36. Procedure NewOverView {( var OV_pagePict : bitMap; 
  37.                        var OV : WindowPtr; 
  38.                        viewRect : Rect;
  39.                        factor : Real )};
  40. var
  41.     dummyRect    :    Rect;
  42.     horizontal,                        {horiz. pixel size of the OverView window}
  43.     vertical    :    Extended;        {vert. pixel size of the OverView window}
  44.     sizeOfOff    :    Size;            {bytes needed for offscreen bitmap}
  45.     offRowBytes    :    Integer;        {row bytes needed for offscreen bitmap}
  46.     bitRect        :    Rect;            {size of OV window and offscreen bitmap}
  47.     dummy        :    Point;
  48.     offPort,                        {temporary working port}
  49.     oldPort        :    GrafPtr;        {temporary storage}
  50. begin
  51.     {compute available vertical screen space}
  52.     vertical := ScreenBits.bounds.bottom-ScreenBits.bounds.top-MenuBarHeight;
  53.     vertical := vertical * factor;
  54.  
  55.     {compute horizontal to proportion}
  56.     horizontal := vertical * viewRect.right / viewRect.bottom;
  57.  
  58.     {create the new window record}
  59.     SetRect(dummyRect,0,0,Num2Integer(horizontal),Num2Integer(vertical));
  60.     OV := NewWindow( nil,dummyRect,'',FALSE,altDBoxProc,WindowPtr(-1),
  61.                     FALSE,LongInt(0) );
  62.  
  63.     {create offscreen bitmap}
  64.     bitRect := OV^.portRect;
  65.     offRowBytes := ((bitRect.right-bitRect.left) div 8) + 1;
  66.     if Odd( offRowBytes ) then offRowBytes := offRowBytes - 1;
  67.     sizeOfOff := (bitRect.bottom-bitRect.top) * offRowBytes;
  68.     with OV_pagePict do
  69.         begin
  70.             baseAddr := QDPtr( NewPtr( sizeOfOff ));
  71.             rowBytes := offRowBytes;
  72.             bounds   := bitRect;
  73.         end;
  74.     
  75.     {fill the bitmap with white}
  76.     GetPort( oldPort );                
  77.     offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
  78.     OpenPort( offPort );
  79.     SetPortBits( OV_pagePict );
  80.     FillRect( bitRect, white );
  81.     SetPort( oldPort );
  82.     ClosePort( offPort );
  83.     DisposPtr( Ptr( offPort ));
  84. end; {MakeOverView}
  85.  
  86. {--------------------------------------------------------------------------}
  87. Procedure UpdateOverView {( drawProc : Procedure;
  88.                           OV_pagePict : bitMap)};
  89. var
  90.     offPort,
  91.     oldPort        :    GrafPtr;
  92. begin
  93.     GetPort( oldPort );
  94.     offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
  95.     OpenPort( offPort );
  96.     SetPortBits( OV_pagePict );        {make all drawing happen offscreen}
  97.  
  98.     drawProc;                        {let the user draw}
  99.  
  100.     SetPort( oldPort );                {return drawing to normal}
  101.     ClosePort( offPort );
  102.     DisposPtr( Ptr( offPort ));
  103. end; {UpdateOverView}
  104.  
  105. {--------------------------------------------------------------------------}
  106. Procedure OverViewSelect{( where: Point; 
  107.                     viewRect : Rect; VAR scrollPosition : Point; 
  108.                     VAR OV : WindowPtr; VAR OV_pagePict : bitMap; 
  109.                     HScrollBar,VScrollBar : ControlHandle)};
  110. var
  111.     MenuFlash        : ^Integer;        {system global}
  112.  
  113.     value,                            {value returned by TrackGrayRgn}
  114.     h, v            : LongInt;        {}
  115.  
  116.     pane,                            {}
  117.     tempPt            : Point;        {}
  118.  
  119.     scope,                            {size of window pane scaled into OV window}
  120.     tempRect,
  121.     limitRect,                        {limit for drag region}
  122.     slopRect        : Rect;            {slopiness allowance for dragging}
  123.  
  124.     dragRectRgn        : RgnHandle;    {the region the user drags around}
  125.     oldPort            : GrafPtr;
  126.     theWindow        : WindowPtr;    {holds the value of frontWindow}
  127.     underScope        : BitMap;        {dynamically allocated offscreen bitmap}
  128.     whichWindow     : WindowPtr;    {for save and restore bits}
  129.     {----------------------------------}
  130.     Procedure OV_Prepare;
  131.     begin
  132.         MenuFlash := pointer($A24);
  133.  
  134.         GetPort( oldPort );
  135.         theWindow := FrontWindow;    {theWindow refers to the active window on entry}
  136.         BringToFront( OV );            {make OV appear, but not really}
  137.         SetPort( OV );                {it's now the current port}
  138.         ShowHide( OV, FALSE );        {it's also not visible}
  139.         MoveWindow( OV,0,0,FALSE );    {home the window}
  140.  
  141.         {compute the size of the current window pane}
  142.         pane.h := theWindow^.portRect.right - theWindow^.portRect.left - sBarWidth;
  143.         pane.v := theWindow^.portRect.bottom - theWindow^.portRect.top - sBarHeight;
  144.  
  145.         {scale the pane into the OV window to show size relative to document}
  146.         SetRect( tempRect, 0, 0, pane.h, pane.v );
  147.         MapRect( tempRect, viewRect, OV^.portRect );
  148.         scope := tempRect;
  149.  
  150.         {make the region to drag around.  same size as scope}        
  151.         dragRectRgn := NewRgn;
  152.         RectRgn( dragRectRgn,scope );
  153.         
  154.         {believe it or not, this works to limit the movement of dragRectRgn}
  155.         SetRect( limitRect, 0, 0, OV^.portRect.right-scope.right+1,
  156.                                   OV^.portRect.bottom-scope.bottom+1 );
  157.  
  158.         {scale scrollPosition into OV for placing scope in OV}
  159.         tempPt := scrollPosition;
  160.         MapPt( tempPt, viewRect, OV^.portRect );
  161.         OffSetRect( scope, tempPt.h, tempPt.v );
  162.  
  163.     end; {OV_Prepare}
  164.     {----------------------------------}
  165.     Procedure OV_PositionOverView;
  166.     var offset : Point;
  167.     begin
  168.         SetPort( oldPort );
  169.         
  170.         offset := where;
  171.         GlobalToLocal ( offset );
  172.         h := offset.h;        {this is the local value of the point of mousedown}
  173.         v := offset.v;
  174.         
  175.         {make sure it doesn't go off the bottom of the window}
  176.         if (v + OV^.portRect.bottom) >= theWindow^.portRect.bottom
  177.             then v := theWindow^.portRect.bottom - OV^.portRect.bottom - 1;
  178.         {make sure it doesn't go off the right of the window}
  179.         if (h + OV^.portRect.right) >= theWindow^.portRect.right
  180.             then h := theWindow^.portRect.right - OV^.portRect.right - 1;
  181.         {make sure it doesn't go off the top of the window}
  182.         if v < theWindow^.portRect.top then v := theWindow^.portRect.top;
  183.         {make sure it doesn't go off the left of the window}
  184.         if h < theWindow^.portRect.left then h := theWindow^.portRect.left;
  185.         
  186.         SetPt ( offset, h, v);
  187.         LocalToGlobal( offset );
  188.         h := offset.h;
  189.         v := offset.v;
  190.         
  191.         SetPort( OV );
  192.         MoveWindow( OV, h, v, FALSE );
  193.     end; {OV_PositionOverView}
  194.     {----------------------------------}
  195.     procedure OV_SaveBits;
  196.     var
  197.         sizeOfOff    :    Size;
  198.         offRowBytes    :    Integer;
  199.         underRect,
  200.         bitRect        :    Rect;
  201.         dummy        :    Point;
  202.         offPort,
  203.         oldPort        :    GrafPtr;
  204.     begin
  205.         GetPort( oldPort );
  206.     
  207.         {put the window magager port into offport as a windowptr}
  208.         GetWMgrPort( offPort );
  209.         whichWindow := WindowPtr( offPort );
  210.  
  211.         {allocate a new grafport}
  212.         offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
  213.         
  214.         {home a copy of the bounds of the OV window}
  215.         bitRect := OV^.portBits.bounds;
  216.         offsetRect( bitRect, -bitrect.left, -bitrect.top );
  217.  
  218.         {compute memory necessary for offscreen bitmap}
  219.         {allocate it and setup bitmap record}
  220.         offRowBytes := ( bitRect.right div 8 ) + 1;
  221.         if Odd( offRowBytes ) then offRowBytes := offRowBytes -1;
  222.         sizeOfOff := bitRect.bottom * offRowBytes;
  223.         with underScope do
  224.         begin
  225.             baseAddr := QDPtr( NewPtr( sizeOfOff ));
  226.             rowbytes := offRowBytes;
  227.             bounds   := bitRect;    {using HOMEd rectangle}
  228.         end;
  229.  
  230.         {move a copy (to ensure no scaling occurs) back where OV will appear}
  231.         underRect := underScope.bounds;
  232.         OffsetRect( underRect, h-1, v-1 );    
  233.  
  234.         {actually save the bits}
  235.         OpenPort( offPort );
  236.         SetPortBits( underScope );
  237.         SetClip( offPort^.visRgn );
  238.         CopyBits( whichWindow^.portBits, underScope,
  239.                   underRect, underScope.bounds,
  240.                   srcCopy, NIL);
  241.         SetPort( oldPort );
  242.         ClosePort( offPort );
  243.         DisposPtr( Ptr( offPort ));    
  244.     end; {OV_SaveBits}
  245.     {----------------------------------}
  246.     Procedure OV_ShowOverView;
  247.     var
  248.         boxWidth, 
  249.         boxHeight: integer;
  250.     begin 
  251.         OV_SaveBits;
  252.         ShowHide( OV, TRUE );        {now the window appears}
  253.         
  254.         {blast miniature picture into OV}
  255.         CopyBits(OV_pagePict,          OV^.portBits, 
  256.                  OV_pagePict.bounds, OV^.portRect,
  257.                  srcCopy,nil);
  258.         
  259.         {highlight the current selection}
  260.         InvertRect( scope );
  261.         
  262.         {give the user some room to be sloppy}
  263.         slopRect := OV^.portRect;
  264.         InsetRect( slopRect, -25, -25 );
  265.  
  266.         GlobalToLocal( where );
  267.  
  268.         {compute size of the draggable region and center it on the cursor}
  269.         boxWidth := scope.right - scope.left;
  270.         boxHeight := scope.bottom - scope.top;
  271.         OffsetRgn( dragRectRgn, where.h-(boxWidth div 2), 
  272.                                 where.v-(boxHeight div 2) );
  273.         OffSetRect( limitRect, boxWidth div 2, boxHeight div 2); 
  274.  
  275.         {let the user drag it around}
  276.         value := DragGrayRgn( dragRectRgn,where,limitRect,slopRect,0,nil );
  277.         
  278.     end; {OV_ShowOverView}
  279.     {----------------------------------}
  280.     Procedure OV_RestoreBits;
  281.     var underRect: Rect;
  282.     begin
  283.          underRect := underScope.bounds;
  284.  
  285.         {home the rectangle}
  286.          OffsetRect( underRect, -underRect.left, -underRect.top);
  287.         
  288.         {position it correctly}
  289.          OffSetRect( underRect, h-1, v-1);
  290.         
  291.         {blast stuff under window back into position}
  292.         CopyBits( underScope, whichWindow^.portBits, 
  293.                   underScope.bounds, underRect,
  294.                   srcCopy, NIL);
  295.         
  296.         {deallocate the bitmap space (be nice and clean)}
  297.         DisposPtr( Ptr( underScope.baseAddr ));
  298.     end; {OV_RestoreBits}
  299.     {----------------------------------}
  300.     Procedure OV_HandleSelection;
  301.         {------------------------}
  302.         Procedure OV_FlashSelection;
  303.         var i: Integer;
  304.             j: LongInt;
  305.         begin
  306.             HLock( Handle( dragRectRgn ));        {try to make this a habit!}
  307.             for i := 1 to 2*MenuFlash^ do begin
  308.                 InvertRect( dragRectRgn^^.rgnBBox );
  309.                 delay( 4,j );
  310.             end;
  311.             HUnLock( Handle( dragRectRgn ));    {but don't forget this part}
  312.         end;
  313.         {------------------------}
  314.     begin {OV_HandleSelection}
  315.         if (HiWord(value)<>-32768) or (LoWord(value)<>-32768)
  316.         then                         {user actually made a selection}
  317.             begin
  318.                 InvertRect( scope );    {turn off current selection}
  319.                 OV_FlashSelection;
  320.                 ShowHide( OV, FALSE );    {hide the OV window}
  321.                 SetPort( oldPort );
  322.                 OV_RestoreBits;            {blast bits back into place}
  323.  
  324.                 {figure the new scrollPosition based on the top-left corner}
  325.                 {of the draggable region}
  326.                 SetPt( tempPt, dragRectRgn^^.rgnBBox.left, dragRectRgn^^.rgnBBox.top );
  327.                 MapPt( tempPt, OV^.portRect, viewRect );
  328.                 scrollPosition := tempPt;
  329.                 
  330.                 tempRect := viewRect;
  331.                 tempRect.bottom := tempRect.bottom - pane.v;
  332.                 tempRect.right := tempRect.right - pane.h;
  333.                 MapPt ( tempPt, tempRect, viewRect );
  334.                 
  335.                 {set the new scroll bar values}
  336.                 SetCtlValue( HScrollBar, tempPt.h );
  337.                 SetCtlValue( VScrollBar, tempPt.v );
  338.                 InvalRect( theWindow^.portRect );
  339.             end
  340.         else         {no selection was made}
  341.             begin
  342.                 ShowHide( OV, FALSE );        {hide the window}
  343.                 SetPort( oldPort );
  344.                 OV_RestoreBits;                {replace the underneath bits}
  345.                 BeginUpdate( theWindow );    {steal the update events}
  346.                 EndUpdate  ( theWindow );
  347.             end;
  348.     end; {OV_HandleSelection}
  349.     {----------------------------------}
  350.     Procedure OV_TidyUp;
  351.     begin
  352.         DisposeRgn( dragRectRgn );
  353.     end; {OV_TidyUp}
  354.     {----------------------------------}
  355. begin
  356.     OV_Prepare;
  357.     OV_PositionOverView;
  358.     OV_ShowOverView;
  359.     OV_HandleSelection;
  360.     OV_TidyUp;
  361. end; {OverViewSelect}
  362.  
  363. END. {UNIT OverView}